﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using CANDataIO;
using DataDefine;
using ECANPort;
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
using UsingEventAggregator.Core;
using Forms = System.Windows.Forms;
using HCC = HandyControl.Controls;

namespace TLDNs.ViewModels
{

    public class RunParameterMonitor : BindableBase, IComparable
    {
        private int _Index;
        /// <summary>
        /// 表格的绝对Index
        /// </summary>
        public int Index
        {
            get { return _Index; }
            set { SetProperty(ref _Index, value); }
        }

        private bool _Monitor;
        public bool Monitor
        {
            get { return _Monitor; }
            set
            {
                SetProperty(ref _Monitor, value);
                if (CheckAction != null)
                {
                    CheckAction((Index, value));
                }
            }
        }


        private RunParameter _Info;
        public RunParameter Info
        {
            get { return _Info; }
            set { SetProperty(ref _Info, value); }
        }


        public string DeviceName { get; set; }
        public int DevIndex;
        public int DevOfParamIndex;
        public Action<(int Index, bool Chk)> CheckAction;
        public RunParameterMonitor(int i, RunParameter f, int dev, int dev_pa, string devName, Action<(int Index, bool Chk)> ac)
        {
            Index = i;
            Info = f;
            Monitor = false;
            DevIndex = dev;
            DevOfParamIndex = dev_pa;
            DeviceName = devName;
            CheckAction = ac;
        }

        public int CompareTo(object obj)
        {
            return DevOfParamIndex.CompareTo(((RunParameterMonitor)obj).DevOfParamIndex);
        }
    }

    public class ParameterMonitoringViewModel : CanDevViewModelBase
    {
        public ParameterMonitoringViewModel(IContainerExtension Container, IRegionManager rm, IEventAggregator ea) : base(Container, rm, ea)
        {
            SFMFileIsReLoaded();

            _ea.GetEvent<GeneralSettingIsChangeEvent>().Subscribe(new Action<object>((obj) =>
            {
                GeneralSettingPar par = (GeneralSettingPar)obj;
                CurUserAccessLv = (AccessLv)par.UserAccessLv;

            }));
            CurUserAccessLv = Properties.Settings.Default.CurUserAccessLv;

            CanDev.ECAN_RecvDataEvent += CanDev_ECAN_RecvDataEvent;
            _ea.GetEvent<RefreshCanEvent>().Subscribe(RefreshCanEvent_Sub);
            _ea.GetEvent<SyncInnerToUIEvent>().Subscribe(SyncInnerToUIEvent_Sub);
            _ea.GetEvent<SaveToCanSystemEvent>().Subscribe(SaveToCanSystemEvent_Sub);
            _ea.GetEvent<MonitorDataEvent>().Subscribe(MonitorDataEvent_Sub);
        }

        private void MonitorDataEvent_Sub(int st, int sp)
        {
            if (dg_all != null)
            {
                List<int> Indexs = new List<int>();
                for (int i = st; i < dg_all.Items.Count; i += sp)
                {
                    RunParameterMonitor item = (RunParameterMonitor)dg_all.Items[i];
                    Indexs.Add(item.Index);
                }

                for (int i = 0; i < Indexs.Count; i++)
                {
                    DataList[Indexs[i]].Monitor = true;
                }
            }
        }
        private void MonitorDataEvent_Sub(MonitorType obj)
        {
            switch (obj)
            {
                case MonitorType.Pri:
                    MonitorDataEvent_Sub(1, 2);
                    break;
                case MonitorType.Odd:
                    MonitorDataEvent_Sub(0, 2);
                    break;
                case MonitorType.All:
                    MonitorDataEvent_Sub(0, 1);
                    break;
                default:
                    break;
            }
        }

        public void SaveToCanSystemEvent_Sub_WriteData(uint CanID, decimal Cur, byte st_addr)
        {
            HMIHelper.HMIDateFrame data = new HMIHelper.HMIDateFrame();
            data.Addr_Start = st_addr;
            data.ByteCount = 2;
            data.Can_Fc = Can_Fc.Write;
            if (Cur > ushort.MaxValue)
                Cur = ushort.MaxValue;
            if (Cur < ushort.MinValue)
                Cur = ushort.MinValue;
            ushort tmpCur = (ushort)Cur;

            data.Data0 = new byte[2];
            data.Data0[0] = (byte)(tmpCur & 0xFF);
            data.Data0[1] = (byte)(tmpCur >> 8);
            CAN_OBJ info = HMIHelper.CreateWrite(CanID, data);
            if (CanDev.CanCount > 0)
                CanDevWriteData(info);
        }


        private void SaveToCanSystemEvent_Sub((bool AutoSaveToInherSFM, bool EqualWrite) flag)
        {
            if (SFM.Devices.Length <= 0)
            {
                HCC.Growl.Info("Save To Can System Failed!");
                return;
            }

            if (SFM.Devices[ZhuDrive.DeviceIndex].Parameters.Length <= ZhuDrive.DataItemCount)
            {
                HCC.Growl.Info("Save To Can System Failed!");
                return;
            }

            for (int i = 0; i < ZhuDrive.DataItemCount - ZhuDrive.PassivityDataItemCount; i++)
            {
                VRWType rwtype = SFM.Devices[ZhuDrive.DeviceIndex].Parameters[ZhuDrive.PassivityDataItemCount + i].ReadWriteType;
                if (rwtype == VRWType.ReadOnly || rwtype == VRWType.PassivityReadOnly)
                    continue;

                var ss = TLDCanDataSet.InherDoc.Devices[ZhuDrive.DeviceIndex].Parameters[ZhuDrive.PassivityDataItemCount + i].Value;
                var Cur = SFM.Devices[ZhuDrive.DeviceIndex].Parameters[ZhuDrive.PassivityDataItemCount + i].Value;

                if (flag.EqualWrite || Cur != ss || ss == 0)// ss =0表示从未读过或写过或者本身为0  flag.EqualWrite 表示即使参数相同也写入
                {
                    //Console.WriteLine($"NB:{ss}  -  UI:{Cur}");
                    SaveToCanSystemEvent_Sub_WriteData(ZhuDrive.ZhuDriveHMICanID, Cur, (byte)(i * 2));
                }
                if (flag.AutoSaveToInherSFM && Cur != ss)
                {
                    TLDCanDataSet.InherDoc.Devices[ZhuDrive.DeviceIndex].Parameters[ZhuDrive.PassivityDataItemCount + i].Value = Cur;
                }
            }

            if (SFM.Devices.Length <= 1)
            {
                HCC.Growl.Info("Save To Can System Failed!");
                return;
            }
            if (SFM.Devices[Pump.DeviceIndex].Parameters.Length <= Pump.DataItemCount)
            {
                HCC.Growl.Info("Save To Can System Failed!");
                return;
            }

            for (int i = 0; i < Pump.DataItemCount - Pump.PassivityDataItemCount; i++)
            {
                VRWType rwtype = SFM.Devices[Pump.DeviceIndex].Parameters[Pump.PassivityDataItemCount + i].ReadWriteType;
                if (rwtype == VRWType.ReadOnly || rwtype == VRWType.PassivityReadOnly)
                    continue;

                var ss = TLDCanDataSet.InherDoc.Devices[Pump.DeviceIndex].Parameters[Pump.PassivityDataItemCount + i].Value;
                var Cur = SFM.Devices[Pump.DeviceIndex].Parameters[Pump.PassivityDataItemCount + i].Value;

                if (flag.EqualWrite || Cur != ss)
                {
                    Console.WriteLine($"NB:{ss}  -  UI:{Cur}");
                    SaveToCanSystemEvent_Sub_WriteData(Pump.PumpHMICanID, Cur, (byte)(i * 2));
                }
                if (flag.AutoSaveToInherSFM && Cur != ss)
                {
                    TLDCanDataSet.InherDoc.Devices[Pump.DeviceIndex].Parameters[Pump.PassivityDataItemCount + i].Value = Cur;
                }
            }

        }

        private void ReadALLHMIData()
        {

            int C = ZhuDrive.DataItemCount - ZhuDrive.PassivityDataItemCount; //需要读的个数
            const int dec = (ZhuDrive.DataItemCount - ZhuDrive.PassivityDataItemCount) % 2;
            for (int i = 0; i < C - dec; i += 2)
            {
                HMIHelper.HMIDateFrame data = new HMIHelper.HMIDateFrame();
                data = HMIHelper.HMIDateFrame.CreateReadFrame((byte)(i * 2), 4);
                CAN_OBJ info = HMIHelper.CreateRead(ZhuDrive.ZhuDriveHMICanID, data);
                CanDevWriteData(info);
            }
            if (dec > 0)
            {
                HMIHelper.HMIDateFrame data = new HMIHelper.HMIDateFrame();
                int i = ZhuDrive.DataItemCount - ZhuDrive.PassivityDataItemCount - 1;
                data = HMIHelper.HMIDateFrame.CreateReadFrame((byte)(i * 2), 2);
                CAN_OBJ info = HMIHelper.CreateRead(ZhuDrive.ZhuDriveHMICanID, data);
                CanDevWriteData(info);
            }


            C = Pump.DataItemCount - Pump.PassivityDataItemCount;
            const int dec2 = (Pump.DataItemCount - Pump.PassivityDataItemCount) % 2;
            for (int i = 0; i < C - dec2; i += 2)
            {
                HMIHelper.HMIDateFrame data = new HMIHelper.HMIDateFrame();
                data = HMIHelper.HMIDateFrame.CreateReadFrame((byte)(i * 2), 4);
                CAN_OBJ info = HMIHelper.CreateRead(Pump.PumpHMICanID, data);
                CanDevWriteData(info);
            }
            if (dec2 > 0)
            {
                HMIHelper.HMIDateFrame data = new HMIHelper.HMIDateFrame();
                int i = Pump.DataItemCount - Pump.PassivityDataItemCount - 1;
                data = HMIHelper.HMIDateFrame.CreateReadFrame((byte)(i * 2), 2);
                CAN_OBJ info = HMIHelper.CreateRead(Pump.PumpHMICanID, data);
                CanDevWriteData(info);
            }
        }

        private void SyncInnerToUIEvent_Sub()
        {
            TLDCanDataSet.Sync(TLDCanDataSet.InherDoc, SFM);
        }
        private void RefreshCanEvent_Sub()
        {
            TLDCanDataSet.Sync(TLDCanDataSet.InherDoc, SFM);
            CAN_OBJ obj = HMIHelper.CreateRead(ZhuDrive.ZhuDriveHMICanID, HMIHelper.HMIDateFrame.CreateStopCANtxFrame());
            CanDevWriteData(obj);
            obj = HMIHelper.CreateRead(Pump.PumpHMICanID, HMIHelper.HMIDateFrame.CreateStopCANtxFrame());
            CanDevWriteData(obj);



            Task syncread = new Task(() =>
            {
                ReadALLHMIData();
            });

            int Slend = 256 * Properties.Settings.Default.SEND_MSG_Hz_ms;
            if (Slend < 1000)
                Slend = 1000;

            syncread.ContinueWith((t) =>
            {
                for (int i = 0; i < 4; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    TLDCanDataSet.Sync(TLDCanDataSet.InherDoc, SFM);
                }

                if (IsNotMonitoring == true)// 不在监控中，恢复数据
                {
                    obj = HMIHelper.CreateRead(ZhuDrive.ZhuDriveHMICanID, HMIHelper.HMIDateFrame.CreateRelaseCanBusFrame());
                    CanDevWriteData(obj);
                    obj = HMIHelper.CreateRead(Pump.PumpHMICanID, HMIHelper.HMIDateFrame.CreateRelaseCanBusFrame());
                    CanDevWriteData(obj);
                }
                System.Threading.Thread.Sleep(1000);
                TLDCanDataSet.Sync(TLDCanDataSet.InherDoc, SFM);
            });

            syncread.Start();
        }

        private void CanDev_ECAN_RecvDataEvent(CAN_OBJ info, uint CanIndex)
        {
            TLDCanDataSet.Resolve(info);
            _ea.GetEvent<CanRecvCountChangeEvent>().Publish();
            //2. TODO:通知
        }

        private SFMDocument _SFM;
        public SFMDocument SFM
        {
            get { return _SFM; }
            set
            {
                SetProperty(ref _SFM, value);
            }
        }

        private ObservableCollection<RunParameterMonitor> _DataList = new ObservableCollection<RunParameterMonitor>();
        public ObservableCollection<RunParameterMonitor> DataList
        {
            get { return _DataList; }
            set { SetProperty(ref _DataList, value); }
        }

        private ObservableCollection<RunParameterMonitor> _MonitorList = new ObservableCollection<RunParameterMonitor>();
        public ObservableCollection<RunParameterMonitor> MonitorList
        {
            get { return _MonitorList; }
            set
            {
                SetProperty(ref _MonitorList, value);
            }
        }


        private void CCCC((int Index, bool Chk) pa)
        {
            if (pa.Chk)
            {
                MonitorCheckedCommand_sub(pa.Index);
            }
            else
            {
                MonitorUnCheckedCommand_sub(pa.Index);
            }
        }

        private void MonitorCheckedCommand_sub(int? tableIndex)
        {
            if (tableIndex != null)
            {
                var tmp = DataList[tableIndex.Value];
                DataList[tableIndex.Value] = tmp;
                if (MonitorList.Contains(tmp) == false)
                    MonitorList.Add(tmp);
            }
        }

        private void MonitorUnCheckedCommand_sub(int? tableIndex)
        {
            if (tableIndex != null)
            {
                var tmp = DataList[tableIndex.Value];
                RunParameterMonitor del = new RunParameterMonitor(-1, null, 0, 0, "", CCCC);
                foreach (var item in MonitorList)
                {
                    if (item.Index == tmp.Index)
                    {
                        del = item;
                        break;
                    }
                }

                if (del.Index >= 0)
                {
                    bool ok = MonitorList.Remove(del);
                }
                DataList[tableIndex.Value] = tmp;
            }
        }

        private bool _IsNotMoritor = true;
        public bool IsNotMonitoring
        {
            get { return _IsNotMoritor; }
            set { SetProperty(ref _IsNotMoritor, value); }
        }

        private bool _NotInCacheing = true;
        public bool NotInCacheing
        {
            get { return _NotInCacheing; }
            set { SetProperty(ref _NotInCacheing, value); }
        }

        private int _CurCacheCount = 0;
        /// <summary>
        /// 当前缓存了多少条数据
        /// </summary>
        public int CurCacheCount
        {
            get { return _CurCacheCount; }
            set { SetProperty(ref _CurCacheCount, value); }
        }

        private int _CacheCount = 10000;
        /// <summary>
        /// 缓存多少条数据
        /// </summary>
        public int CacheCount
        {
            get { return _CacheCount; }
            set { SetProperty(ref _CacheCount, value); }
        }

        public Collection<(DateTime, ArraySegment<decimal>)> CacheDataColl;

        private int _DelayMs = 1000;
        public int DelayMs
        {
            get { return _DelayMs; }
            set { SetProperty(ref _DelayMs, value); }
        }

        Task ReadDataTask;
        Random rand = new Random();
        private Control MinitorControlUI;
        /// <summary>
        /// Cache几个项目
        /// </summary>
        private int CurCacheItemCount = 0;
        List<string> CacheItemHeaders = new List<string>();

        private void MonitorEvent_Sub_ReadData(uint CanID, byte st_addr, byte ByteCount)
        {
            HMIHelper.HMIDateFrame data = new HMIHelper.HMIDateFrame();
            data.Addr_Start = st_addr;
            // 
            data.ByteCount = ByteCount;
            data.Can_Fc = Can_Fc.Read;
            CAN_OBJ info = HMIHelper.CreateRead(CanID, data);
            CanDevWriteData(info);
        }



        private void ReadOneData(RunParameterMonitor pa, byte ByteCount)
        {
            byte addr;
            switch (pa.DevIndex)
            {
                case 0:
                    //只有类似Modbus协议定义的数据才能主动读
                    if (pa.DevOfParamIndex >= ZhuDrive.PassivityDataItemCount && pa.DevOfParamIndex < ZhuDrive.DataItemCount)
                    {
                        addr = (byte)(2 * (pa.DevOfParamIndex - ZhuDrive.PassivityDataItemCount));
                        MonitorEvent_Sub_ReadData(ZhuDrive.ZhuDriveHMICanID, addr, ByteCount);
                    }

                    break;
                case 1:
                    //只有类似Modbus协议定义的数据才能主动读
                    if (pa.DevOfParamIndex >= Pump.PassivityDataItemCount && pa.DevOfParamIndex < Pump.DataItemCount)
                    {
                        addr = (byte)(2 * (pa.DevOfParamIndex - Pump.PassivityDataItemCount));
                        MonitorEvent_Sub_ReadData(Pump.PumpHMICanID, addr, ByteCount);
                    }
                    break;
                default:
                    break;
            }

        }

        /// <summary>
        /// 读数据策略
        /// </summary>
        public enum ReadDataStrategy
        {
            /// <summary>
            /// 一个一个的读
            /// </summary>
            OnceRead,
            /// <summary>
            /// 1个连续的地址
            /// </summary>
            Continuation,
            /// <summary>
            /// 1个连续读几个然后带几个零散的
            /// </summary>
            ContinuationWithN,
            /// <summary>
            /// 分成几个连续的片段读
            /// 需要判断上一个片段是否读完
            /// </summary>
            MultContinuation
        }
        public struct ReadDataStrategyRt
        {
            public ReadDataStrategy Strategy;
            public byte Start;
            public byte Count;
        }


        ReadDataStrategyRt CheckReadDataTaskStrategy(List<byte> Addrs)
        {
            ReadDataStrategyRt rt = new ReadDataStrategyRt();
            Addrs.Sort();
            int NotContinuationCount = 0;
            if (Addrs.Count >= 2)
            {
                int tmp = Addrs[0];
                //TODO：获取几个连续片段
                for (int i = 1; i < Addrs.Count; i++)
                {
                    if (Addrs[i] - tmp > 1)
                    {
                        NotContinuationCount++;
                    }
                    tmp = Addrs[i];
                }

                if (NotContinuationCount > 5)
                {
                    rt.Strategy = ReadDataStrategy.OnceRead;
                }
                else if (NotContinuationCount == 0)
                {
                    rt.Strategy = ReadDataStrategy.Continuation;
                    rt.Start = Addrs[0];
                    if (Addrs.Count * 2 < 255)
                    {
                        rt.Count = (byte)(Addrs.Count * 2);
                    }
                    else
                    {
                        rt.Count = 254;
                    }

                }
                else
                {
                    //rt = ReadDataStrategy.ContinuationWithN;
                    //int Start = ZhuDriveAddrs[0];
                }
            }
            else
            {
                rt.Strategy = ReadDataStrategy.Continuation;
                rt.Start = Addrs[0];
                rt.Count = (byte)(Addrs.Count * 2);
            }
            return rt;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        (ReadDataStrategyRt ZhuDrive, ReadDataStrategyRt Pump) CheckReadDataTaskStrategy()
        {
            List<byte> ZhuDriveAddrs = new List<byte>();
            List<byte> PumpAddrs = new List<byte>();
            for (int i = 0; i < MonitorList.Count; i++)
            {
                if (MonitorList[i].DevIndex == ZhuDrive.DeviceIndex)
                {
                    byte addr = (byte)(2 * (MonitorList[i].DevOfParamIndex - ZhuDrive.PassivityDataItemCount));
                    ZhuDriveAddrs.Add(addr);
                }
                if (MonitorList[i].DevIndex == Pump.DeviceIndex)
                {
                    byte addr = (byte)(2 * (MonitorList[i].DevOfParamIndex - ZhuDrive.PassivityDataItemCount));
                    PumpAddrs.Add(addr);
                }
            }
            ReadDataStrategyRt rt1 = CheckReadDataTaskStrategy(ZhuDriveAddrs);
            ReadDataStrategyRt rt2 = CheckReadDataTaskStrategy(PumpAddrs);

            return (rt1, rt2);
        }

        /// <summary>
        /// 可以连续返回
        /// </summary>
        void ReadDataTaskContinuation_Sub(uint CanID, ReadDataStrategyRt pa)
        {
            HMIHelper.HMIDateFrame data = new HMIHelper.HMIDateFrame();
            data.Addr_Start = pa.Start;
            data.ByteCount = pa.Count;
            data.Can_Fc = Can_Fc.HMI_读多个;
            CAN_OBJ info = HMIHelper.CreateRead(CanID, data);
            CanDevWriteData(info);
        }


        private int SortMonitorList(ObservableCollection<RunParameterMonitor> MList)
        {
            List<RunParameterMonitor> Pump = new List<RunParameterMonitor>();
            List<RunParameterMonitor> Zhu = new List<RunParameterMonitor>();
            ObservableCollection<RunParameterMonitor> rt = new ObservableCollection<RunParameterMonitor>();
            for (int i = 0; i < MonitorList.Count; i++)
            {
                if (MonitorList[i].DevIndex == 0)
                {
                    Zhu.Add(MonitorList[i]);
                }
                if (MonitorList[i].DevIndex == 1)
                {
                    Pump.Add(MonitorList[i]);
                }
            }
            Pump.Sort();
            Zhu.Sort();

            rt.AddRange(Zhu);
            rt.AddRange(Pump);
            MonitorList = rt;
            return Zhu.Count;
        }


        private decimal[] ReadMonitorList()
        {
            decimal[] data = new decimal[MonitorList.Count];
            int C = 0;
            for (int i = 0; i < MonitorList.Count; i++)
            {
                bool DoubleRead = false;
                var pa = MonitorList[i];
                if (i + 1 < MonitorList.Count)
                {
                    var panext = MonitorList[i + 1];
                    if (pa.DevIndex == panext.DevIndex && pa.DevOfParamIndex + 1 == panext.DevOfParamIndex)
                    {
                        DoubleRead = true;
                    }
                }

                if (DoubleRead)
                {
                    ReadOneData(pa, 4);
                    C += 2;
                    decimal val = TLDCanDataSet.GetOneData(pa.DevIndex, pa.DevOfParamIndex);
                    MonitorList[i].Info.Value = val;
                    data[i] = val;
                    val = TLDCanDataSet.GetOneData(pa.DevIndex, pa.DevOfParamIndex + 1);
                    i++;
                    MonitorList[i].Info.Value = val;
                    data[i] = val;
                }
                else
                {
                    ReadOneData(pa, 2);
                    C++;
                    decimal val = TLDCanDataSet.GetOneData(pa.DevIndex, pa.DevOfParamIndex);
                    MonitorList[i].Info.Value = val;
                    data[i] = val;
                }
            }
            //Console.WriteLine($"MC={MonitorList.Count}  C={C}");
            return data;
        }

        /// <summary>
        /// 发一个返回一个
        /// </summary>
        void ReadDataTask_Sub()
        {
            int C = CacheCount;
            CacheDataColl = new Collection<(DateTime, ArraySegment<decimal>)>();
            decimal[] data = new decimal[0];
            NotInCacheing = false;
            CurCacheCount = 0;
            CurCacheItemCount = MonitorList.Count;
            double tmp = ((double)CurCacheItemCount) / _DelayMs;
            if (tmp > 0.1)//每10ms一条
            {
                //提示信息
            }

            CacheItemHeaders = new List<string>();
            CacheItemHeaders.Add($"{LangDic["TimeString"]}");
            for (int i = 0; i < MonitorList.Count; i++)
            {
                CacheItemHeaders.Add(MonitorList[i].Info.ParameterName);
            }
            while (C >= 0 && CurCacheItemCount > 0 && IsNotMonitoring == false && CanDevIsOnline)
            {
                C--;
                MinitorControlUI.Dispatcher.BeginInvoke(new Action(() =>
                {
                    data = ReadMonitorList();
                    if (CurCacheCount < CacheCount && data.Length > 0)
                    {
                        ArraySegment<decimal> dataLine = new ArraySegment<decimal>(data);

                        CacheDataColl.Add((DateTime.Now, dataLine));
                        CurCacheCount++;
                    }
                }));


                System.Threading.Thread.Sleep(_DelayMs);
            }
            NotInCacheing = true;
            // 无限监控
            while (IsNotMonitoring == false && CanDevIsOnline)
            {
                MinitorControlUI.Dispatcher.BeginInvoke(new Action(() =>
                {
                    ReadMonitorList();
                }));
                System.Threading.Thread.Sleep(_DelayMs);
            }

            if (CanDevIsOnline == false)
            {
                HCC.Growl.Info($"{LangDic["CanNotOnline"]}");
            }
            IsNotMonitoring = true;
        }

        public DelegateCommand<Control> StartMonitorCommand => new DelegateCommand<Control>(StartMonitorCommand_sub);
        private void StartMonitorCommand_sub(Control g)
        {
            SortMonitorList(MonitorList);
            if (CanDevIsOnline)
            {
                if (Properties.Settings.Default.StartMonitorStopOther)
                {
                    CAN_OBJ obj = HMIHelper.CreateRead(ZhuDrive.ZhuDriveHMICanID, HMIHelper.HMIDateFrame.CreateStopCANtxFrame());
                    CanDevWriteData(obj);
                    obj = HMIHelper.CreateRead(Pump.PumpHMICanID, HMIHelper.HMIDateFrame.CreateStopCANtxFrame());
                    CanDevWriteData(obj);
                }
                MinitorControlUI = g;

                ReadDataTask = new Task(ReadDataTask_Sub);
                ReadDataTask.Start();

                IsNotMonitoring = false;
            }
            else
            {
                HCC.Growl.Info($"{LangDic["CanNotOnline"]}");
            }
        }

        public DelegateCommand ExportMonitorCommand => new DelegateCommand(ExportMonitorCommand_sub);
        private void ExportMonitorCommand_sub()
        {
            MonitorDataExportPc = 0;
            if (MonitorList != null && CurCacheItemCount > 0 && CurCacheCount > 0)
            {
                //  Pa1 ,Pa2,Pa3
                //  2   3    5 
                // 12   23   58
                Forms.SaveFileDialog save = new Forms.SaveFileDialog();
                save.Filter = $"Excel{LangDic["File"]}(*.xls)|*.xls";
                save.Title = $"{LangDic["SaveFileTitle"]}";
                save.FileName = "MonitorDataExport_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-sss.fff") + ".xls";

                if (save.ShowDialog() == Forms.DialogResult.OK)
                {
                    Task.Run(() =>
                    {
                        Excel2007 excel = new Excel2007();
                        excel.Save(save.FileName, CacheItemHeaders, CacheDataColl, "Sheet1",
                            new Action<double>(UpdateMonitorDataExport), Properties.Settings.Default.ExportReadOnly);
                        HCC.Growl.Info($"{LangDic["ExportOk"]}");
                        CurCacheItemCount = 0;
                        CacheDataColl.Clear();
                    });
                }
            }
            else
            {
                HCC.Growl.Info($"{LangDic["NoDateExport"]}");
                MonitorDataExportPc = 0;
            }

        }

        private int _MonitorDataExportPc;
        public int MonitorDataExportPc
        {
            get { return _MonitorDataExportPc; }
            set { SetProperty(ref _MonitorDataExportPc, value); }
        }

        private void UpdateMonitorDataExport(double pc)
        {
            MonitorDataExportPc = (int)Math.Round(pc * 100, 1);
        }

        public DelegateCommand StopMonitorCommand => new DelegateCommand(StopMonitorCommand_sub);
        private void StopMonitorCommand_sub()
        {
            IsNotMonitoring = true;
            NotInCacheing = true;
            if (CanDevIsOnline)
            {
                CanDev.ClearSendBuff();
                if (Properties.Settings.Default.StopMonitorReleaseOther)
                {
                    CAN_OBJ obj = HMIHelper.CreateRead(ZhuDrive.ZhuDriveHMICanID, HMIHelper.HMIDateFrame.CreateRelaseCanBusFrame());
                    CanDevWriteData(obj);
                    obj = HMIHelper.CreateRead(Pump.PumpHMICanID, HMIHelper.HMIDateFrame.CreateRelaseCanBusFrame());
                    CanDevWriteData(obj);
                }

            }
            else
            {
                HCC.Growl.Info($"{LangDic["CanNotOnline"]}");
            }

        }



        /// <summary>
        /// 监控选中项
        /// </summary>    
        public DelegateCommand MonitorSelectCommand => new DelegateCommand(MonitorSelectCommand_Sub);
        private void MonitorSelectCommand_Sub()
        {
            if (dg_all != null)
            {
                List<int> Indexs = new List<int>();
                for (int i = 0; i < dg_all.SelectedItems.Count; i++)
                {
                    RunParameterMonitor item = (RunParameterMonitor)dg_all.SelectedItems[i];
                    Indexs.Add(item.Index);
                }

                for (int i = 0; i < Indexs.Count; i++)
                {
                    DataList[Indexs[i]].Monitor = true;
                }
            }
        }

        /// <summary>
        /// 取消监控选中项
        /// </summary>    
        public DelegateCommand UnMonitorSelectCommand => new DelegateCommand(UnMonitorSelectCommand_Sub);
        private void UnMonitorSelectCommand_Sub()
        {
            if (dg_all != null)
            {
                List<int> Indexs = new List<int>();
                for (int i = 0; i < dg_all.SelectedItems.Count; i++)
                {
                    RunParameterMonitor item = (RunParameterMonitor)dg_all.SelectedItems[i];
                    Indexs.Add(item.Index);
                }

                for (int i = 0; i < Indexs.Count; i++)
                {
                    DataList[Indexs[i]].Monitor = false;
                }
            }
        }

        private DataGrid dg_all;
        /// <summary>
        /// 控件加载
        /// </summary>    
        public DelegateCommand<DataGrid> UILoadedEvent2Command => new DelegateCommand<DataGrid>(UILoadedEvent2Command_Sub);
        private void UILoadedEvent2Command_Sub(DataGrid par)
        {
            dg_all = par;
        }

        private DataGrid dg_Monitor;
        /// <summary>
        /// 控件加载
        /// </summary>    
        public DelegateCommand<DataGrid> UILoadedEvent3Command => new DelegateCommand<DataGrid>(UILoadedEvent3Command_Sub);
        private void UILoadedEvent3Command_Sub(DataGrid par)
        {
            dg_Monitor = par;
        }
        /// <summary>
        /// 取消监控选中项
        /// </summary>    
        public DelegateCommand UnMonitorSelectCommand2 => new DelegateCommand(UnMonitorSelectCommand2_Sub);
        private void UnMonitorSelectCommand2_Sub()
        {
            if (dg_Monitor != null)
            {
                List<int> Indexs = new List<int>();
                for (int i = 0; i < dg_Monitor.SelectedItems.Count; i++)
                {
                    RunParameterMonitor item = (RunParameterMonitor)dg_Monitor.SelectedItems[i];
                    Indexs.Add(item.Index);
                }

                for (int i = 0; i < Indexs.Count; i++)
                {
                    DataList[Indexs[i]].Monitor = false;
                }
            }
        }



        protected override void SFMFileIsReLoaded()
        {
            SFM = SFMDocument.Create();
            DataList.Clear();
            int C = SFM.Devices.Length;
            if (C <= 0)
                return;
            LoadDataListTask(0, C);
        }

        private void LoadDataListTask(int tabindex, int C)
        {
            if (C <= 0)
                return;
            App.UIDispatcherDoAction(() =>
            {
                for (int i = 0; i < C; i++)
                {
                    int ParCount = SFM.Devices[i].Parameters.Length;
                    for (int j = 0; j < ParCount; j++)
                    {
                        DataList.Add(new RunParameterMonitor(tabindex, SFM.Devices[i].Parameters[j], i, j, SFM.Devices[i].DeviceInfo.DeviceName, CCCC));
                        tabindex++;
                    }
                }
            });
        }


        private AccessLv _CurUserAccessLv = AccessLv.User;
        public AccessLv CurUserAccessLv
        {
            get { return _CurUserAccessLv; }
            set
            {
                SetProperty(ref _CurUserAccessLv, value);
            }
        }

    }
}
